using SqlQueryBuilder.Util;

namespace SqlQueryBuilder.Clauses
{
    /// <summary>
    /// Class that compare a field/column whith any kind of value
    /// </summary>
    public class Compare : AbstractValueClause, IConditionalClause
    {
        private readonly string field;
        private readonly Comparision comparisionType;
        private readonly object value;

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Compare"/> class.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="comparisionType">Type of the comparision.</param>
        /// <param name="value">The value.</param>
        public Compare(string field, Comparision comparisionType, object value)
        {
            this.field = field;
            this.comparisionType = comparisionType;
            this.value = value;
        }

        #endregion

        /// <summary>
        /// Builds the where clause.
        /// </summary>
        /// <returns></returns>
        public string BuildConditionalClause()
        {
            return CreateClause();
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static Compare Eq(string field, object value)
        {
            return new Compare(field, Comparision.Eq, value);
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="sqlLiteral">The SQL literal.</param>
        /// <returns></returns>
        public static Compare Eq(string field, SqlLiteral sqlLiteral)
        {
            return new Compare(field, Comparision.Eq, sqlLiteral);
        }

        /// <summary>
        /// Comparision operator using a SqlLiteral
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="literal">The literal.</param>
        /// <returns></returns>
        public static Compare EqLiteral(string field, string literal)
        {
            return new Compare(field, Comparision.Eq, new SqlLiteral(literal));
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static Compare NEq(string field, object value)
        {
            return new Compare(field, Comparision.NEq, value);
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="sqlLiteral">The SQL literal.</param>
        /// <returns></returns>
        public static Compare NEq(string field, SqlLiteral sqlLiteral)
        {
            return new Compare(field, Comparision.NEq, sqlLiteral);
        }

        /// <summary>
        /// Ns the eq literal.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="literal">The literal.</param>
        /// <returns></returns>
        public static Compare NEqLiteral(string field, string literal)
        {
            return new Compare(field, Comparision.NEq, new SqlLiteral(literal));
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static Compare Ge(string field, object value)
        {
            return new Compare(field, Comparision.Ge, value);
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="sqlLiteral">The SQL literal.</param>
        /// <returns></returns>
        public static Compare Ge(string field, SqlLiteral sqlLiteral)
        {
            return new Compare(field, Comparision.Ge, sqlLiteral);
        }

        /// <summary>
        /// Ges the literal.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="literal">The literal.</param>
        /// <returns></returns>
        public static Compare GeLiteral(string field, string literal)
        {
            return new Compare(field, Comparision.Ge, new SqlLiteral(literal));
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static Compare Le(string field, object value)
        {
            return new Compare(field, Comparision.Le, value);
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="sqlLiteral">The SQL literal.</param>
        /// <returns></returns>
        public static Compare Le(string field, SqlLiteral sqlLiteral)
        {
            return new Compare(field, Comparision.Le, sqlLiteral);
        }

        /// <summary>
        /// Les the literal.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="literal">The literal.</param>
        /// <returns></returns>
        public static Compare LeLiteral(string field, string literal)
        {
            return new Compare(field, Comparision.Le, new SqlLiteral(literal));
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static Compare Gt(string field, object value)
        {
            return new Compare(field, Comparision.Gt, value);
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="sqlLiteral">The SQL literal.</param>
        /// <returns></returns>
        public static Compare Gt(string field, SqlLiteral sqlLiteral)
        {
            return new Compare(field, Comparision.Gt, sqlLiteral);
        }

        /// <summary>
        /// Gts the literal.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="literal">The literal.</param>
        /// <returns></returns>
        public static Compare GtLiteral(string field, string literal)
        {
            return new Compare(field, Comparision.Gt, new SqlLiteral(literal));
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static Compare Lt(string field, object value)
        {
            return new Compare(field, Comparision.Lt, value);
        }

        /// <summary>
        /// Comparision operator
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="sqlLiteral">The SQL literal.</param>
        /// <returns></returns>
        public static Compare Lt(string field, SqlLiteral sqlLiteral)
        {
            return new Compare(field, Comparision.Lt, sqlLiteral);
        }

        /// <summary>
        /// Lts the literal.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="literal">The literal.</param>
        /// <returns></returns>
        public static Compare LtLiteral(string field, string literal)
        {
            return new Compare(field, Comparision.Lt, new SqlLiteral(literal));
        }

        /// <summary>
        /// Creates the clause.
        /// </summary>
        /// <returns></returns>
        private string CreateClause()
        {
            return string.Format("{0} {1} {2}", field, GetComparisionType(), FormatSQLValue(value));
        }

        /// <summary>
        /// Gets the type of the comparision.
        /// </summary>
        /// <returns></returns>
        private string GetComparisionType()
        {
            switch (comparisionType)
            {
                case Comparision.Eq: return "=";
                case Comparision.NEq: return "<>";
                case Comparision.Ge: return ">=";
                case Comparision.Gt: return ">";
                case Comparision.Le: return "<=";
                default: return "<";
            }
        }
    }
}